Merge "Adding a bunch of hooks from wikiHow into DifferenceEngine, 2nd try"
[lhc/web/wiklou.git] / includes / auth / AuthManager.php
index 0a4bd68..82eeff0 100644 (file)
@@ -558,7 +558,7 @@ class AuthManager implements LoggerAwareInterface {
                                        );
                                        $ret->neededRequests[] = $ret->createRequest;
                                }
-                               $this->fillRequests( $ret->neededRequests, self::ACTION_LOGIN, null );
+                               $this->fillRequests( $ret->neededRequests, self::ACTION_LOGIN, null, true );
                                $session->setSecret( 'AuthManager::authnState', [
                                        'reqs' => [], // Will be filled in later
                                        'primary' => null,
@@ -878,10 +878,22 @@ class AuthManager implements LoggerAwareInterface {
        /**
         * Determine whether a particular account can be created
         * @param string $username
-        * @param int $flags Bitfield of User:READ_* constants
+        * @param array $options
+        *  - flags: (int) Bitfield of User:READ_* constants, default User::READ_NORMAL
+        *  - creating: (bool) For internal use only. Never specify this.
         * @return Status
         */
-       public function canCreateAccount( $username, $flags = User::READ_NORMAL ) {
+       public function canCreateAccount( $username, $options = [] ) {
+               // Back compat
+               if ( is_int( $options ) ) {
+                       $options = [ 'flags' => $options ];
+               }
+               $options += [
+                       'flags' => User::READ_NORMAL,
+                       'creating' => false,
+               ];
+               $flags = $options['flags'];
+
                if ( !$this->canCreateAccounts() ) {
                        return Status::newFatal( 'authmanager-create-disabled' );
                }
@@ -905,7 +917,7 @@ class AuthManager implements LoggerAwareInterface {
                        $this->getPrimaryAuthenticationProviders() +
                        $this->getSecondaryAuthenticationProviders();
                foreach ( $providers as $provider ) {
-                       $status = $provider->testUserForCreation( $user, false );
+                       $status = $provider->testUserForCreation( $user, false, $options );
                        if ( !$status->isGood() ) {
                                return Status::wrap( $status );
                        }
@@ -1010,7 +1022,9 @@ class AuthManager implements LoggerAwareInterface {
                        return AuthenticationResponse::newFail( $status->getMessage() );
                }
 
-               $status = $this->canCreateAccount( $username, User::READ_LOCKING );
+               $status = $this->canCreateAccount(
+                       $username, [ 'flags' => User::READ_LOCKING, 'creating' => true ]
+               );
                if ( !$status->isGood() ) {
                        $this->logger->debug( __METHOD__ . ': {user} cannot be created: {reason}', [
                                'user' => $username,
@@ -1575,11 +1589,15 @@ class AuthManager implements LoggerAwareInterface {
                }
 
                // Denied by providers?
+               $options = [
+                       'flags' => User::READ_LATEST,
+                       'creating' => true,
+               ];
                $providers = $this->getPreAuthenticationProviders() +
                        $this->getPrimaryAuthenticationProviders() +
                        $this->getSecondaryAuthenticationProviders();
                foreach ( $providers as $provider ) {
-                       $status = $provider->testUserForCreation( $user, $source );
+                       $status = $provider->testUserForCreation( $user, $source, $options );
                        if ( !$status->isGood() ) {
                                $ret = Status::wrap( $status );
                                $this->logger->debug( __METHOD__ . ': Provider denied creation of {username}: {reason}', [
@@ -1650,7 +1668,7 @@ class AuthManager implements LoggerAwareInterface {
                        throw $ex;
                }
 
-               $this->setDefaultUserOptions( $user, true );
+               $this->setDefaultUserOptions( $user, false );
 
                // Inform the providers
                $this->callMethodOnProviders( 6, 'autoCreatedAccount', [ $user, $source ] );
@@ -1677,6 +1695,10 @@ class AuthManager implements LoggerAwareInterface {
                        $logid = $logEntry->insert();
                }
 
+               // Commit database changes, so even if something else later blows up
+               // the newly-created user doesn't get lost.
+               wfGetLBFactory()->commitMasterChanges( __METHOD__ );
+
                if ( $login ) {
                        $this->setSessionDataForUser( $user );
                }
@@ -2056,7 +2078,7 @@ class AuthManager implements LoggerAwareInterface {
                }
 
                // Fill in reqs data
-               $this->fillRequests( $reqs, $providerAction, $options['username'] );
+               $this->fillRequests( $reqs, $providerAction, $options['username'], true );
 
                // For self::ACTION_CHANGE, filter out any that something else *doesn't* allow changing
                if ( $providerAction === self::ACTION_CHANGE || $providerAction === self::ACTION_REMOVE ) {
@@ -2073,10 +2095,13 @@ class AuthManager implements LoggerAwareInterface {
         * @param AuthenticationRequest[] &$reqs
         * @param string $action
         * @param string|null $username
+        * @param boolean $forceAction
         */
-       private function fillRequests( array &$reqs, $action, $username ) {
+       private function fillRequests( array &$reqs, $action, $username, $forceAction = false ) {
                foreach ( $reqs as $req ) {
-                       $req->action = $action;
+                       if ( !$req->action || $forceAction ) {
+                               $req->action = $action;
+                       }
                        if ( $req->username === null ) {
                                $req->username = $username;
                        }
@@ -2121,6 +2146,37 @@ class AuthManager implements LoggerAwareInterface {
                return true;
        }
 
+       /**
+        * Get a provider by ID
+        * @note This is public so extensions can check whether their own provider
+        *  is installed and so they can read its configuration if necessary.
+        *  Other uses are not recommended.
+        * @param string $id
+        * @return AuthenticationProvider|null
+        */
+       public function getAuthenticationProvider( $id ) {
+               // Fast version
+               if ( isset( $this->allAuthenticationProviders[$id] ) ) {
+                       return $this->allAuthenticationProviders[$id];
+               }
+
+               // Slow version: instantiate each kind and check
+               $providers = $this->getPrimaryAuthenticationProviders();
+               if ( isset( $providers[$id] ) ) {
+                       return $providers[$id];
+               }
+               $providers = $this->getSecondaryAuthenticationProviders();
+               if ( isset( $providers[$id] ) ) {
+                       return $providers[$id];
+               }
+               $providers = $this->getPreAuthenticationProviders();
+               if ( isset( $providers[$id] ) ) {
+                       return $providers[$id];
+               }
+
+               return null;
+       }
+
        /**@}*/
 
        /**
@@ -2270,34 +2326,6 @@ class AuthManager implements LoggerAwareInterface {
                return $this->secondaryAuthenticationProviders;
        }
 
-       /**
-        * Get a provider by ID
-        * @param string $id
-        * @return AuthenticationProvider|null
-        */
-       protected function getAuthenticationProvider( $id ) {
-               // Fast version
-               if ( isset( $this->allAuthenticationProviders[$id] ) ) {
-                       return $this->allAuthenticationProviders[$id];
-               }
-
-               // Slow version: instantiate each kind and check
-               $providers = $this->getPrimaryAuthenticationProviders();
-               if ( isset( $providers[$id] ) ) {
-                       return $providers[$id];
-               }
-               $providers = $this->getSecondaryAuthenticationProviders();
-               if ( isset( $providers[$id] ) ) {
-                       return $providers[$id];
-               }
-               $providers = $this->getPreAuthenticationProviders();
-               if ( isset( $providers[$id] ) ) {
-                       return $providers[$id];
-               }
-
-               return null;
-       }
-
        /**
         * @param User $user
         * @param bool|null $remember
@@ -2330,7 +2358,7 @@ class AuthManager implements LoggerAwareInterface {
        private function setDefaultUserOptions( User $user, $useContextLang ) {
                global $wgContLang;
 
-               \MediaWiki\Session\SessionManager::singleton()->invalidateSessionsForUser( $user );
+               $user->setToken();
 
                $lang = $useContextLang ? \RequestContext::getMain()->getLanguage() : $wgContLang;
                $user->setOption( 'language', $lang->getPreferredVariant() );